    //
//  SearchViewController.m
//  PhoneBook
//
//  Created by valkyrie on 8/18/10.
//  Copyright 2010 __MyCompanyName__. All rights reserved.
//

#import "SearchViewController.h"
#import "PhoneBookTableCell.h"
#import "YahooXPathResource.h"
#import "PhoneBook.h"

@implementation SearchViewController

//@synthesize keywordText;
//@synthesize searchBtn;
@synthesize phoneSearchBar;
@synthesize phoneListTableView, phoneArray;
@synthesize searcher;
@synthesize conn;
@synthesize doSearchAlert, disableViewOverlay;


// search bar event [start]

- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
	// add a cancel button
	[searchBar setShowsCancelButton:YES animated:YES];
	
	// add a overlay
	self.disableViewOverlay.alpha = 0;
	[self.view addSubview:self.disableViewOverlay];
	[UIView beginAnimations:@"FadeIn" context:nil];
	[UIView setAnimationDuration:0.5];
	self.disableViewOverlay.alpha = 0.6;
	[UIView commitAnimations];
	
	[self.navigationController setNavigationBarHidden:YES animated:YES];
	
}

/* 
 called when keyboard search button pressed 
 we go to search yahoo api here.
 */
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
	
	// hiden search bar keyboard
	[searchBar resignFirstResponder];
	[self performSelector:@selector(enableSearchBarCancelButton:) withObject:searchBar];
	
	NSString *keyword = [searchBar.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
	
	if ([keyword length] == 0) {
		UIAlertView *kwErrAlert = [[UIAlertView alloc] initWithTitle:@"Please input a keyword" message:nil delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
		[kwErrAlert show];
		[kwErrAlert release];
		return;
	}
	
	if (searcher) {
		[searcher release];
	}
	
	searcher = [PhoneBookSearchFactory initPhoneNumSearcherByType:PHONE_SEARCHER_WEB];
	
	//NSLog(@"Search Reference Count %d", [searcher retainCount]);
	
    [searcher queryForArrayAsyn:keyword delegate:self];
	
	if(self.conn != nil && self.doSearchAlert == nil) {
		UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"検索中" message:nil delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:nil];
		
		self.doSearchAlert = alert;
		
		[alert show];
		[alert release];
	}	
	
}

- (void)searchBarCancelButtonClicked:(UISearchBar *) searchBar {
	[searchBar setText:@""];
	[searchBar setShowsCancelButton:NO animated:YES];
	[searchBar resignFirstResponder];
	[self.disableViewOverlay removeFromSuperview];
	[self.navigationController setNavigationBarHidden:NO animated:YES];
	
	// return default view
	if(self.phoneListTableView) {
		[self.phoneListTableView removeFromSuperview];
	}
}

// keep the search bar cancel button enbale after bar resign
- (void)enableSearchBarCancelButton:(UISearchBar *) searchBar {

	for (id subview in [searchBar subviews]) {
		if([subview isKindOfClass:[UIButton class]]) {
			[subview setEnabled:YES];
			break;
		}
	}
	
}

// search bar event [end]

- (IBAction) keywordDoneEditing: (id) sender {
	[sender resignFirstResponder];
}

/*
- (IBAction) doSearchPhoneNumber: (id) sender {
	NSString *keyword = [keywordText.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
	
	if ([keyword length] == 0) {
		UIAlertView *kwErrAlert = [[UIAlertView alloc] initWithTitle:@"Please input a keyword" message:nil delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
		[kwErrAlert show];
		[kwErrAlert release];
		return;
	}
	
	if (searcher) {
		[searcher release];
	}
	
	searcher = [PhoneBookSearchFactory initPhoneNumSearcherByType:PHONE_SEARCHER_WEB];

	//NSLog(@"Search Reference Count %d", [searcher retainCount]);
	
    [searcher queryForArrayAsyn:keyword delegate:self];
	
	if(self.conn != nil && self.doSearchAlert == nil) {
		UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Search In Progress" message:nil delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:nil];
		
		self.doSearchAlert = alert;
		
		[alert show];
		[alert release];
	}
	
}
*/

- (void) parseYahooPhoneDetail:(xmlNode *)curNode storeArray:(NSMutableArray *)resultArr forIndex:(NSInteger)findex {

	PhoneBook *pbook = nil;
	xmlXPathContextPtr xpathCtx = nil;
	xmlXPathObjectPtr xpathNameObj = nil;
	xmlXPathObjectPtr xpathAddrObj = nil;
	xmlXPathObjectPtr xpathGenreObj = nil;
	xmlXPathObjectPtr xpathPNumObj = nil;
	
	NSString *xpathNameExpWithLink = XPATH_COMP_NAME_WITH_LINK;
	NSString *xpathNameExp = XPATH_COMP_NAME;
	
	NSString *xpathAddrExp = XPATH_ADDRESS;
	
	NSString *xpathGenreExp = XPATH_GENRE;
	
	NSString *xpathPNumExp = XPATH_PHONE_NUMBER;
	
	@try {

		xpathCtx = xmlXPathNewContext(curNode);
		if (xpathCtx == nil) {
			NSLog(@"parseYahooPhoneDetail xpahtCtx is nil.");
			return;
		}

		pbook = [PhoneBook alloc];
		
		// parse company name
		 xpathNameObj = xmlXPathEvalExpression((xmlChar *)[xpathNameExpWithLink cStringUsingEncoding:NSUTF8StringEncoding], xpathCtx);		
		
		 if (xpathNameObj == nil || xpathNameObj->nodesetval == nil) {
			 if (xpathNameObj) {
				 xmlXPathFreeObject(xpathNameObj);
			 }
			 xpathNameObj = xmlXPathEvalExpression((xmlChar *)[xpathNameExp cStringUsingEncoding:NSUTF8StringEncoding], xpathCtx);			 
			 if (xpathNameObj == nil) {
				 NSLog(@"NO name Object found.");
				 return;
			 }
		 }
		
		if (xpathNameObj->nodesetval->nodeNr > 0) {
			NSString *companyName = [NSString stringWithCString:(const char *)xpathNameObj->nodesetval->nodeTab[0]->content encoding:NSUTF8StringEncoding];
			pbook.name = companyName;
		}		
		 
		// parse address
		xpathAddrObj = xmlXPathEvalExpression((xmlChar *)[xpathAddrExp cStringUsingEncoding:NSUTF8StringEncoding], xpathCtx);		
		
		if(xpathAddrObj != nil && xpathAddrObj->nodesetval != nil && xpathAddrObj->nodesetval->nodeNr > 0) {
			NSString *addr = [NSString stringWithCString:(const char *)xpathAddrObj->nodesetval->nodeTab[0]->content encoding:NSUTF8StringEncoding];
			addr = [addr stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
			addr = [addr stringByReplacingOccurrencesOfString:@" / 業種：" withString:@""];
			pbook.address = addr;
		}
		 
		
		// parse genre
		xpathGenreObj = xmlXPathEvalExpression((xmlChar *)[xpathGenreExp cStringUsingEncoding:NSUTF8StringEncoding], xpathCtx);		
		
		if(xpathGenreObj != nil && xpathGenreObj->nodesetval != nil && xpathGenreObj->nodesetval->nodeNr > 0) {
			NSString *gen = [NSString stringWithCString:(const char *)xpathGenreObj->nodesetval->nodeTab[0]->content encoding:NSUTF8StringEncoding];
			pbook.genre = gen;
		}
		
		// parse phone number
		xpathPNumObj = xmlXPathEvalExpression((xmlChar *)[xpathPNumExp cStringUsingEncoding:NSUTF8StringEncoding], xpathCtx);		
		
		if(xpathPNumObj != nil && xpathPNumObj->nodesetval != nil && xpathPNumObj->nodesetval->nodeNr > 0) {
			NSString *pnum = [NSString stringWithCString:(const char *)xpathPNumObj->nodesetval->nodeTab[0]->content encoding:NSUTF8StringEncoding];
			pnum = [pnum stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
			pbook.phoneNumber = pnum;
		}		
		

		[resultArr addObject:pbook];
		
	}
	@catch (NSException * e) {
		NSLog(@"ERR %@ %@", [e name], [e reason]);
	}
	@finally {
		if(pbook)
			[pbook release];
		
		if(xpathNameObj)
			xmlXPathFreeObject(xpathNameObj);
		
		if(xpathAddrObj)
			xmlXPathFreeObject(xpathAddrObj);
		
		if (xpathGenreObj)
			xmlXPathFreeObject(xpathGenreObj);
		
		if (xpathPNumObj)
			xmlXPathFreeObject(xpathPNumObj);
		
		if(xpathCtx)
			xmlXPathFreeContext(xpathCtx);
		
	}		
}

- (NSMutableArray *) parseYahooXml {
	
	NSMutableArray *resultNodes = [[NSMutableArray alloc] init];
	
	xmlDocPtr doc = nil;
	xmlXPathContextPtr xpathCtx = nil;
	xmlXPathObjectPtr xpathDetailList = nil;
	NSString *xpathDetailExp = XPATH_DETAIL_LIST;
	//xmlXPathObjectPtr xpathPageInfo;	
	
	@try {
		
		doc = htmlReadMemory([recieveData bytes], [recieveData length], "", NULL, HTML_PARSE_NOWARNING | HTML_PARSE_NOERROR);
		
		if (doc == nil) {
			NSLog(@"The Document is nil.");
			return resultNodes;
		}
		
		// create xml path context by html document
		xpathCtx = xmlXPathNewContext(doc);
		if (xpathCtx == nil) {
			NSLog(@"The xpahtCtx is nil.");
			return resultNodes;
		}
		
		xpathDetailList = xmlXPathEvalExpression((xmlChar *)[xpathDetailExp cStringUsingEncoding:NSUTF8StringEncoding], xpathCtx);
		if (xpathDetailList == nil) {
			NSLog(@"The xpathDetailList is nil.");
			return resultNodes;
		}
		
		xmlNodeSetPtr results = xpathDetailList->nodesetval;	
		
		if (results && results->nodeNr > 0) {
			
			for (NSInteger i = 0; i < results->nodeNr; i++) {
				[self parseYahooPhoneDetail:results->nodeTab[i] storeArray:resultNodes forIndex:i];
			}
		}
		
	}
	@catch (NSException *e) {
		NSLog(@"ERR %@ %@", [e name], [e reason]);
	}
	@finally {
		if (xpathDetailList) {
			xmlXPathFreeObject(xpathDetailList);
		}
		
		if(xpathCtx) {
			xmlXPathFreeContext(xpathCtx);
		}
		
		if(doc) {
			xmlFreeDoc(doc);
		}
				
	}		
	
	return resultNodes;
}

// query for yahoo api
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
	
	if (!recieveData) {
		recieveData = [[NSMutableData alloc] init];
	}
	else {
		[recieveData setLength:0];
	}

	
}

// get yahoo data
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
	
	[recieveData appendData:data];
}

// success to get data from yahoo. all data transfer completely
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
	
	//NSString* content = [[NSString alloc] initWithData:recieveData encoding:NSUTF8StringEncoding];
	//NSLog(@"%@", content);
	//[content release];
	
	//NSLog(@"Connection Hloder Count[%d]", [connection retainCount]);
	
	// release holded connection
	self.conn = nil;	
	
	//NSLog(@"After Connection Hloder Count[%d]", [connection retainCount]);
	
	if(self.doSearchAlert) {
		[self.doSearchAlert dismissWithClickedButtonIndex:0 animated:YES];
		self.doSearchAlert = nil;
	}
	
	NSMutableArray *resultNodes = [self parseYahooXml];
	//NSLog(@"resultNodes Count[%d]", [resultNodes retainCount]);
	for (int i = 0; i < [resultNodes count]; i++) {
		NSLog(@"The Yahoo Data Name[%@] Address[%@] Genre[%@] Phone[%@]", [[resultNodes objectAtIndex:i] name], 
			  [[resultNodes objectAtIndex:i] address],
			  [[resultNodes objectAtIndex:i] genre],
			  [[resultNodes objectAtIndex:i] phoneNumber]);
	}
	
	if( [resultNodes count] > 0 ) {
		// UITableViewStyleGrouped UITableViewStylePlain
		
		CGFloat tbh = self.phoneSearchBar.frame.size.height;
		
		if(self.phoneListTableView) {
			[self.phoneListTableView removeFromSuperview];
		}
		
		self.phoneListTableView = nil;
		self.phoneListTableView = [[UITableView alloc] initWithFrame:CGRectMake(-320.0f, tbh, 320.0f, -416.0f) style:UITableViewStylePlain];
		self.phoneListTableView.delegate = self;
		self.phoneListTableView.dataSource = self;
		
		self.phoneArray = resultNodes;
		
		[self.view addSubview:self.phoneListTableView];	
		
		// Slide In Table View
		[UIView beginAnimations:@"SlideIn" context:nil];
		[UIView setAnimationDuration:0.2];
		//[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.view cache:YES];
		[UIView setAnimationCurve:UIViewAnimationCurveLinear];
		
		self.phoneListTableView.frame = CGRectMake(0.0f, tbh, 320.0f, 416.0f);
		
		[UIView commitAnimations];
				
		
		//UINavigationController *phoneListNav = [[UINavigationController alloc] initWithRootViewController:phoneListViewController];
		
		//self.phoneListTable.phoneArray = resultNodes;
		
		//[self.navigationController presentModalViewController:phoneListNav animated:YES];
		//[self.navigationController pushViewController:self.phoneListTable animated:YES];
		
		//[phoneListViewController release];
		//[phoneListNav release];		
		
	}
	else {
		UIAlertView *noResultAlert = [[UIAlertView alloc] initWithTitle:@"No result found." message:nil delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
		[noResultAlert show];
		[noResultAlert release];		
	}

	[resultNodes release];

	
//	[connection release];
	
}

// error occur when get data from yahoo
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
	
	NSLog(@"ERR: DESC[%@] REASON[%@]", [error localizedDescription], [error localizedFailureReason]);
	
	//NSLog(@"Connection Hloder Count[%d]", [connection retainCount]);
	
	// release holded connection
	self.conn = nil;
	
	if(self.doSearchAlert) {
		[self.doSearchAlert dismissWithClickedButtonIndex:0 animated:YES];
		self.doSearchAlert = nil;
	}	
	
	//NSLog(@"After Connection Hloder Count[%d]", [connection retainCount]);
	
//	[connection release];
	
}

- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
	NSLog(@"Cancel Search.");
	
	self.doSearchAlert = nil;
	
	[self.conn cancel];
	self.conn = nil;
}

#pragma mark -
#pragma mark Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    // Return the number of sections.
    return 1;
}


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    // Return the number of rows in the section.
    return [self.phoneArray count];
}


// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    static NSString *CellIdentifier = @"PhoneResultCell";
    
    PhoneBookTableCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[PhoneBookTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }
    
    // Configure the cell...
    
	cell.name.text = [[self.phoneArray objectAtIndex:indexPath.row] name];
	cell.address.text = [[self.phoneArray objectAtIndex:indexPath.row] address];
	cell.phone.text = [[self.phoneArray objectAtIndex:indexPath.row] phoneNumber];
	
	cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
	
    return cell;
}


/*
 // Override to support conditional editing of the table view.
 - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
 // Return NO if you do not want the specified item to be editable.
 return YES;
 }
 */


/*
 // Override to support editing the table view.
 - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
 
 if (editingStyle == UITableViewCellEditingStyleDelete) {
 // Delete the row from the data source
 [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:YES];
 }   
 else if (editingStyle == UITableViewCellEditingStyleInsert) {
 // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
 }   
 }
 */


/*
 // Override to support rearranging the table view.
 - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
 }
 */


/*
 // Override to support conditional rearranging of the table view.
 - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
 // Return NO if you do not want the item to be re-orderable.
 return YES;
 }
 */


#pragma mark -
#pragma mark Table view delegate

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    // Navigation logic may go here. Create and push another view controller.
	/*
	 <#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:@"<#Nib name#>" bundle:nil];
     // ...
     // Pass the selected object to the new view controller.
	 [self.navigationController pushViewController:detailViewController animated:YES];
	 [detailViewController release];
	 */
}


/*
 // The designated initializer.  Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
        // Custom initialization
    }
    return self;
}
*/

/*
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
}
*/

/**/
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];
	
	UIView *tmpOverlay = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 44.0f, 320.0f, 416.0f)];
	tmpOverlay.backgroundColor = [UIColor blackColor];
	tmpOverlay.alpha = 0;
	self.disableViewOverlay = tmpOverlay;
	[tmpOverlay release];
	
}

- (void)viewDidAppear:(BOOL)animated {
	[super viewDidAppear:animated];
	
}

/*
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/

- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];
    
    // Release any cached data, images, etc that aren't in use.
}

- (void)viewDidUnload {
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}


- (void)dealloc {
	//[keywordText release];
	//[searchBtn release];
	
	[phoneSearchBar release];
	
	[phoneListTableView release];
	
	[phoneArray release];
	
	[recieveData release];
	
	if(searcher) {
		[searcher release];
	}
	
	if(conn) {
		[conn release];
	}
	
	if(doSearchAlert)
		[doSearchAlert release];
	
	[disableViewOverlay release];
	
    [super dealloc];
}


@end
